﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Web.DomainServices;

namespace FlexiCommerce.Components
{
    [Serializable]
    public abstract class HierarchicalPersistenceItem<T> : PersistenceItem, IHierarchicalPersistenceItem where T : PersistenceItem
    {
        private int sortOrder;
        [Persistence.DoNotCopy]
        private T parent = null;

        [Persistence.DoNotCopy]
        private IList<T> children = new List<T>();
        [Exclude]
        public IList<T> Children
        {
            get
            {
                return children;
            }
            set
            {
                children = value;
            }
        }

        [UIHint("Hierarchical_Parent")]
        public T Parent
        {
            get
            {
                return parent;
            }
            set
            {
                parent = value;
            }
        }

        public int SortOrder
        {
            get
            {
                return sortOrder;
            }
            set
            {
                sortOrder = value;
            }
        }
        private const int SortOrderTreshold = 9999;
        public void AddTo(T newParent)
        {
            if (Parent != null && Parent != newParent && Cast<HierarchicalPersistenceItem>(Parent).Children.Contains(this as HierarchicalPersistenceItem))
                Cast<HierarchicalPersistenceItem>(Parent).Children.Remove(this as HierarchicalPersistenceItem);

            Parent = newParent;

            if (newParent != null && !Cast<HierarchicalPersistenceItem>(newParent).Children.Contains(this as HierarchicalPersistenceItem))
            {
                IList<HierarchicalPersistenceItem> siblings = Cast<HierarchicalPersistenceItem>(newParent).Children;
                if (siblings.Count > 0)
                {
                    int lastOrder = siblings[siblings.Count - 1].SortOrder;

                    for (int i = siblings.Count - 2; i >= 0; i--)
                    {
                        if (siblings[i].SortOrder < lastOrder - SortOrderTreshold)
                        {
                            siblings.Insert(i + 1, this as HierarchicalPersistenceItem);
                            return;
                        }
                        lastOrder = siblings[i].SortOrder;
                    }

                    if (lastOrder > SortOrderTreshold)
                    {
                        siblings.Insert(0, this as HierarchicalPersistenceItem);
                        return;
                    }
                }

                siblings.Add(this as HierarchicalPersistenceItem);
            }
        }

        private t Cast<t>(object item) where t: class
        {
            if (item is t)
                return item as t;
            return null;
        }


        #region HierarchalPersistenceItem Members



        IHierarchicalPersistenceItem IHierarchicalPersistenceItem.Parent
        {
            get
            {
                return this.Parent as IHierarchicalPersistenceItem;
            }
            set
            {
                this.Parent = value as T;
            }
        }


        #endregion

        #region IHierarchicalPersistenceItem Members

        IList<IHierarchicalPersistenceItem> IHierarchicalPersistenceItem.Children
        {
            get
            {
                IList<IHierarchicalPersistenceItem> newList = new List<IHierarchicalPersistenceItem>();
                foreach (T item in Children)
                {
                    newList.Add(item as IHierarchicalPersistenceItem);
                }
                return newList;
            }
            set
            {
                this.Children = (IList<T>)value;
            }
        }



        #endregion

        #region IHierarchicalPersistenceItem Members


        int IHierarchicalPersistenceItem.SortOrder
        {
            get
            {
                return this.SortOrder;
            }
            set
            {
                this.SortOrder = value;
            }
        }

        void IHierarchicalPersistenceItem.AddTo(IHierarchicalPersistenceItem newParent)
        {
            this.AddTo(newParent as T);
        }

        int IHierarchicalPersistenceItem.ID
        {
            get
            {
                return this.ID;
            }
            set
            {
                this.ID = value;
            }
        }

        #endregion
    }
    [Serializable]
    public abstract class HierarchicalPersistenceItem : HierarchicalPersistenceItem<HierarchicalPersistenceItem>
    {
    }



}
